import scala.collection.immutable.StringOps
import scala.collection.parallel.immutable
//object HelloScala {
//  def main(args: Array[String]): Unit = {
//    println("我的第一个scala程序")
//    System.out.println("调用Java写的程序")
//  }
//
//}
/**
 * 写class 类名时必须引入一个伴生对象，相当于全局变量定义，用object定义
 * main(args:Array[String]):Unit申明在object中
 *
 **/
class Study(name: String, age: Int) {
  def printInfo(): Unit = {
    println(name + " " + age + " " + Study.school)
  }
}

//引入伴生对象,全局只有一份
object Study {
  //申明一个常量
  val school: String = "云南"

  /**
   * scala中一切皆可以用.调用
   * 文档注释，只有在方法面前或者类前面写
   * scala中定义常量用val修饰，定义变量用var修饰
   * scalc中定义变量常量是先写名称后写类型，如：定义变量var i:Int=34
   * 能用常量的地方不用变量，申明常量是类型可以省略，编译器会自动推算
   * 常量val的值不可以改变，new也不可以
   * 标识符的命名规范：
   *    scala中逸字母，下划线开头，后接数字，字母，下划线
   *    逸操作符开头，则只能包含操作符（+-* /等）
   *    用反引号'....'引起来，包括的任意字符串，即使是Scala关键字也可以用
   *字符串输出：通过println(),+号连接
   *          也可以用printf()来拼接，用%来传值，跟c语言用法一样
   *          字符串模板（插值字符串）：通过$获取变量值，如：println(s"${age岁的${}}")
   *          println(s"${age的${}}")
   *          通过字符串模板时要在前面加上s或f
   *          用s""" """三引号可以直接按照原格式输出
   *控制台标准的输入：引用scala中的io中的StdIn类进行：
   *        val name:String=StdIn.readLine()，可以看里面的方法
   *读取文件：引用scala.io.Source类中的方法fromFile()
   *       Source.fromFile().foreach()
   *java中写入东西道文件中：
   *     val writer =new PrintWriter(new File("src\\main\\resources\\outprint.txt"))
   *     writer.write("我日，Java竟然有这个方法")
   *     writer.close()
   *java中的基本包装类型：Character,Byte,Short,Integer,Long,Float,Double,Boolean
   * scala中长整型数在定义时在后面要加 L，定义浮点数时要在后面加上f
   *scala中的基本数据类型：Char,Int,Float,Double,Unit,Null,Nothing,StringOps,Any
   * '\\'表示\自身
   *java中自动类型转换原则：把数据类型从低精度类型转换到高精度类型
   * scala中类型转换原则：谁精度大就转换成谁，（byte,short）和char之间不会相互自动转换
   *            scala中做强制转换在需要强转的东西后面加上toInt类似
   *格式化数据：.formatted("%.2f")
   *运算符：%=求余后再赋值，<<=左移后赋值：c<<=2等于c=c<<2
   *       >>=右移后赋值，scala中没有自加自减
   *当有多种类型的返回值时，可以使用这些类型的公共父类作为返回值
   *
   *循环：
   *    Java中的for语法：for(int i=0;i<10;i++){}
   *    scala中范围遍历操作：for(i<- 1 to 10){}:to遍历的是从1取到10的范围内遍历十次,to是包含最后一个范围值
   *    for(i:Int<- 1 until 10){}:until遍历遍历的是从1到9，不包含最后一个范围值
   *    for循环中可以同时有多个变量进行遍历
   *集合遍历：
   *      for(i<-Array(12,14,18)){},此外，还可以遍历集合List和Set等集合，直接打印输出
   *scala循环守卫：即循环保护式，即循环里面的条件为true则进入循环体内部，为false则跳过，
   *              类似于continue。语法：for(i:Int<- 1 to 10 if i!=2){}
   *   遍历中控制循环的步长用by:for(i<-1 to 10 by 2):步长为2
   *   遍历倒序输出：步长为负可以实现倒序输出，或者通过调用reverse实现反转
   *scala中for循环默认的返回值都是空Unit,在特殊情况下可用yield在for循环中生成一个集合返回
   *        yield 想要返回谁谁就放在它的后面
   *
   * while循环：while里面返回的是一个bool值，当为false时，则条件终止
   * do while用法跟while差不多，但要先执行一次do
   * 推荐使用for循环
   *
   * 循环中断：scala中没有break和continue，scala中退出是用异常中断实现的，
   *          break 相当于throw new RuntimeException"放在try  catch中"
   *          也可以用Breaks.break退出
   *
   *       scala函数式编程：
   *       在main函数里的叫做局部函数，在mian外面定义的叫做对象的方法，是基于对象调用的
   *       可变参数：在参数的数据类型后面加上*号
   *       参数列表中有多个参数时，可变参数要放在后面，对于默认参数，将默认值挡在参数列表后面
   *       scala中每个函数都会以最后一行代码块作为自己的返回值
   *       如果函数体中只有一行代码，可以省略花括号（=号后面的花括号），由编译器自己推断
   *       每个函数体的return关键字都可以省略
   *       如果不要返回值则可以直接省略函数的返回类型
   *       函数返回类型为空，参数为空，则在带调用的时候可以直接用函数名
   *spark中常用匿名函数申明：(name:String)=>{函数体}，也叫lambda表达式，
   *                      调用匿名函数时可以把匿名函数用一个变量值赋值使用
   *                      匿名函数的值就是它的返回值
   *    或者：hanshu((a,b)=>a+b,1,1)
   *         hanshu(_+_,1,1)
   *       匿名函数使用时可以直接把函数当作一个参数值输入到另外一个值
   *       scala中函数可以作为值进行赋值
   *       给函数进行添加一个值叫函数调用，利用函数传值要用使用完整的函数体，写成val f1:Int=>Int=f
   *       闭包函数：函数内部的变量调用到函数外部的东西。
         * 函数可以作为值进行传递：val f1:Int=>Int=f _  //表示f1:Int是参数类型，=>后面是函数返回值类型，f(_)表示的是f这个函数
         * //调用函数体使用函数名加下划线，返回的是函数体对象
         * //调用函数相当于是对函数进行传值，返回的是一个值
   *函数作为参数进行传递（代码例子如下：）
   *   //定义一个函数dualEval(),其返回值是Int,op:(Int,Int)=>Int op()是一个匿名函数，里面有两个参数，返回值为Int
   *       def dualEval(op:(Int,Int)=>Int,a:Int,b:Int):Int={
   *       println("将函数作为参数进行传递")
   *       op(a,b)
   *       }
   *       def add(a:Int,b:Int):Int={
   *       a+b
   *       }
   *       //都是同样的表达
   *       println(dualEval(add,12,12))
   *       println(dualEval(a,b)=>a+b))
   *       println(dualEval(_+_,12,12))
   *可以作为函数返回值返回
   * 编写闭包函数一般使用柯里化编写
   *      函数循环嵌套传值+返回值类型：add(a:Int)(b:Int):Int={//函数体} //有两层函数，返回值为Int
   *
   * scala中递归是必须申明函数返回值的类型
   *      scala中确保是尾递归，可以加上关键字@tailrec
   *传名参数，区别于传值参数，它传的是一个代码块（也叫控制抽象）
   *      传名参数定义：def f2(a: =>Int):Unit={ }
   *    // a =>Int表示传递一个代码块，代码块的返回类型是Int,a表示一个代码块
   *     使用时参数被使用几次，这个函数就会被调用几次
   *
   *
   *
   *
   *
   */
  def main(args: Array[String]): Unit = {
    val alice = new Study("alice", 23)
    val bob = new Study("bob", 24)
    alice.printInfo()
    bob.printInfo()
    val name:String="唐永光"
    val age:Int=23
//    println(_hah)
//    val `if`:String="lalal"
//    println(`if`)
    println(s"${name}在学习${age}")
//    val b2:Long=48498449484897489L
    def m1():Unit={
      println("测试方法")
    }
    val a:Unit=m1()
    println(a)
    println(m1())
    //调用Java下的Student类
//    var student:Student=new Student("lan",123)
//    student=null
//    println(student)
    //范围遍历,
    for(i:Int<- 1 to 10){
      println(i+".hello")
    }
    //循环守卫遍历
    for(i:Int <-1.to(10) if i!=5){
      print("循环守卫跳过条件值："+i)
    }
    //嵌套循环遍历
    for(i:Int<-1 to 5; j:Int<-1 to 5){
      println("i="+i+","+"j="+j)
    }

    /**
     * 以上嵌套循环遍历相当于for(i<-1 to 5){
     *                     for(j<-1until 5){
     *                     }
     *                     }
     */
    //循环体返回值
    val b:IndexedSeq[Int]=for(i<-1 to 10) yield i
    println("b="+b)
    //实现循环中断
    try{
      for(i<-1 until 5){
        if(i==3){
          throw new RuntimeException
        }
        println(i)
      }
    }catch{
      case e:Exception=> //
    }



  }

}
//7月24号看p68
